目录
  1. 1. 基本流程及要点
  2. 2. 面试题目
    1. 2.1. 闭包原理及应用
    2. 2.2. jquery 源码,如 delegate 原理
    3. 2.3. 简述 JS drag 事件以及模拟 drag 事件的方案
    4. 2.4. get 参数通过正则获取 window.location.search
    5. 2.5. 简单介绍 CSS3 动画属性及用法,如何优化动画性能
    6. 2.6. 柯里化连加实现
    7. 2.7. position 关键字值有哪几种,以及相应的表现形式
    8. 2.8. 中间件和插件的区别
    9. 2.9. Bootstrap grid 实现原理。
    10. 2.10. 继承的方式。
    11. 2.11. Canvas SVG 区别。
    12. 2.12. 日期换算,求天数差等
    13. 2.13. let 具体为什么会有临时死域。
    14. 2.14. 监控一个 DOM 替换过程
    15. 2.15. WebSocket 简述原理
    16. 2.16. 冒泡 + 快排 + 插入排序原理等
    17. 2.17. 网络协议 HTTP HTTPS HTTP2 的基本概念等
    18. 2.18. 自适应布局,移动端自适应等问题
    19. 2.19. 设计模式
    20. 2.20. 你怎么看 XXX

360 & 美团前端社招面经及部分面试题

基本流程及要点

一般是至少三轮的技术面 + 一轮 HR 面,三轮技术一定程度上可能是你未来的同事 + 架构 + 上级。

面试题目

闭包原理及应用

jquery 源码,如 delegate 原理

原理利用了JS 事件的事件冒泡机制,在 document(或事件源的父层)进行监听,冒泡到监听点后,判断事件源是否自己设定的元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
function delegate(parent, eventType, selector, fn){
  //参数处理
  if(typeof parent === 'string'){
    var parent = document.getElementById(parent);
    !parent && alert('parent not found');
  }

  if(typeof selector !== 'string'){
      alert('selector is not string');
  }
        
  if(typeof fn !== 'function'){
       alert('fn is not function');
  }
        
  function handle(e){
    // 获取 event 对象
    // 标准 DOM 方法事件处理函数第一个参数是 event 对象
    // IE可以使用全局变量 window.event
    var evt = window.event ? window.event : e;
  
    // 获取触发事件的原始事件源
    // 标准 DOM 方法是用 target 获取当前事件源
    // IE 使用 evt.srcElement 获取事件源
    var target = evt.target || evt.srcElement;
  
    // 获取当前正在处理的事件源
    // 标准 DOM 方法是用 currentTarget 获取当前事件源
    // IE 中的 this 指向当前处理的事件源
    var currentTarget= e ? e.currentTarget : this;

    if(target.id === selector || target.className.indexOf(selector) != -1){
      fn.call(target);
    }
  }
        
  parent[eventType]=handle;
}
    
delegate('container', 'onclick', 'listener', function(){
    alert(this);    
});

简述 JS drag 事件以及模拟 drag 事件的方案

一个完整的 drag and drop 流程通常包含以下几个步骤:

  1. 设置可拖拽目标. 设置属性 draggable="true" 实现元素的可拖拽.

  2. 监听 dragstart 设置拖拽数据

  3. 为拖拽操作设置反馈图标 (可选)

  4. 设置拖放效果, 如 copy, move, link

  5. 设置拖放目标, 默认情况下浏览器阻止所有的拖放操作, 所以需要监听 dragenter 或者 dragover 取消浏览器默认行为使元素可拖放.

  6. 监听 drop 事件执行所需操作

实现 drag

  1. onmousedown + onmousemove → startDrag()

  2. onmouseup → stopDrag()

  3. 偏移值,两次事件的鼠标位置记录: e.pageX || e.clientX + scrollX; e.pageY || e.clientY + scrollY;

1
window.location.search.match(/(([^?&=]+)(=([^?&=]*))*)/g)

简单介绍 CSS3 动画属性及用法,如何优化动画性能

  1. transition

  2. animation

transition 主要设置四个过渡属性:

  • transition-property // 规定设置过渡效果的 CSS 属性的名称。

  • transition-duration // 规定完成过渡效果需要多少秒或毫秒。

  • transition-timing-function // 规定速度效果的速度曲线。

  • transition-delay // 定义过渡效果何时开始。

1
2
3
4
5
6
7
8
9
div{
  width:100px;
  background:blue;
  transition:width 2s;
}

div:hover{
  width:300px;
}

注释:请始终设置 transition-duration 属性,否则时长为 0,就不会产生过渡效果。

  1. animation 属性是一个简写属性,用于设置六个动画属性:
  • animation-name // 规定需要绑定到选择器的 keyframe 名称。
  • animation-duration // 规定完成动画所花费的时间,以秒或毫秒计。
  • animation-timing-function // 规定动画的速度曲线。
  • animation-delay // 规定在动画开始之前的延迟。
  • animation-iteration-count // 规定动画应该播放的次数。
  • animation-direction // 规定是否应该轮流反向播放动画。

优化具体参考即为如下几点:

由于渲染三阶段分为:Layout—>Paint—>Composite,可针对此三者分别进行优化。 优化目标:15FPS 不流畅 ,30FPS+感觉流畅,60FPS舒适完美

触发Layout的方式有:

  • 改变 width, height, margin 等和大小、位置相关的属性
  • 读取 size, position 相关得属性

要点:

  • 使用 transform 代替 top, left 的动画
  • 分离读写,减少 Layout
  • 面对解耦代码,使用 rAF 推迟的方法分离读写。

触发 Paint 的方式:

当修改 border-radius, box-shadow, color 等展示相关属性时,会触发 paint 要点:

  • 简化绘制的复杂度
  • 避免不必要的绘制
  • 减少绘制区域

Composite 小结:

GPU 是有限度的,不要滥用 GPU 资源生成不必要的 Layer 留意意外生成的 Layer

可结合贝塞尔曲线(cubic-bezier),开启硬件加速。will-change 属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
div{
  width:100px;
  height:100px;
  background:red;
  position:relative;
  animation:mymove 5s infinite;
  -webkit-animation:mymove 5s infinite; /*Safari and Chrome*/
}

@keyframes mymove{
  from {left:0px;}
  to {left:200px;}
}

@-webkit-keyframes mymove{
  from {left:0px;}
  to {left:200px;}
}

柯里化连加实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
function add() {
  var sum = 0, i, len;
    for (i = 0, len = arguments.length; i < len; i++) {
    sum += arguments[i];
  }
  return sum;
}

var currying = function(fn) {
        console.log(arguments)
    var _args = [];

    return function cb() {

        if (arguments.length === 0) {
            return fn.apply(this, _args);
        }

        Array.prototype.push.apply(_args, arguments);

        return cb;
    }
}

var curryingAdd = currying(add);

curryingAdd(1)(2)(3)(4)(); // 10

var add321 = curryingAdd(3)(2, 1);

add321(4)(); // 10

position 关键字值有哪几种,以及相应的表现形式

static / relative / absolute / fixed / sticky(新特性)

粘性定位是相对定位和固定定位的混合。元素在跨越特定阈值前为相对定位,之后为固定定位。

其盒位置根据正常流计算,然后相对于该元素在流中的 flow root(BFC)和 containing block(最近的块级祖先元素)定位。在所有情况下,该元素定位均不对后续元素造成影响。当元素 B 被粘性定位时,后续元素的位置仍按照 B 未定位时的位置来确定。position: sticky 对 table 元素的效果与 position: relative 相同。

1
#one { position: sticky; top: 10px; }

中间件和插件的区别

中间件是一种独立的系统软件或服务程序,分布式应用软件借助这种软件在不同的技术之间共享资源。中间件位于客户机 / 服务器的操作系统之上,管理计算机资源和网络通讯。是连接两个独立应用程序或独立系统的软件。相连接的系统即使它们具有不同的接口,但通过中间件相互之间仍能交换信息。执行中间件的一个关键途径是信息传递。通过中间件,应用程序可以工作于多平台或 OS 环境。

插件是一种遵循一定规范的应用程序接口编写出来的程序。

Bootstrap grid 实现原理。

浮动,宽度瓜分,媒体查询,响应式布局。

继承的方式。

原型链继承(对象间的继承) 类式继承(构造函数间的继承) ES6 Class

Canvas SVG 区别。

Canvas 适用场景:

Canvas 提供的功能更原始,适合像素处理,动态渲染和大数据量绘制; Canvas 是使用 JavaScript 程序绘图,提供画布标签和绘制 API(动态生成); Canvas 是基于位图的图像,它不能够改变大小,只能缩放显示;

SVG 适用场景:

SVG 功能更完善,适合静态图片展示,高保真文档查看和打印的应用场景 SVG 是使用 XML 文档描述来绘图,是一整套独立的矢量图形语言; SVG 更适合用来做动态交互,而且 SVG 绘图很容易编辑,只需要增加或移除相应的元素就可以了。 SVG 是基于矢量的,所有它能够很好的处理图形大小的改变。

二者是有不同用途的,作为一个开发者,你应该做的是理解应用程序的具体需求并选择正确的技术来实现它。

日期换算,求天数差等

1
2
3
4
5
var a = '2014-04-23';
var date1 = new Date(a);
var b = '2014-04-24';
var date2 = new Date(b);
var days = Math.floor((date2 - date1) / 1000 / 60 / 60 / 24)

let 具体为什么会有临时死域。

详见JavaScript 变量的生命周期:为什么 let 不存在变量提升

监控一个 DOM 替换过程

原生方法监听 DOM 结构改变事件 https://developer.mozilla.org/en-US/docs/XUL/Events#Mutation_DOM_events

1
2
3
document.addEventListener('DOMNodeInserted',function(){alert(1)},false);
document.addEventListener('DOMAttrModified',function(){alert(1)},false);
document.addEventListener('DOMNodeRemoved',function(){alert(1)},false);

变动事件包括以下不同事件类型:

  • DOMSubtreeModified: 在 DOM 结构中发生任何变化时触发

  • DOMNodeInserted: 在一个节点作为子节点被插入到另一个节点中时触发

  • DOMNodeRemoved: 在节点从其父节点中被移除时触发

  • DOMNodeRemovedFromDocument: 在一个节点被直接从文档中移除或通过子树间接从文档中移除之前触发

  • DOMNodeInsertedIntoDocument: 在一个节点被直接插入文档或通过子树间接插入文档之后触发

  • DOMAttrModified: 在属性被修改之后触发

  • DOMCharacterDataModified: 在文本节点的值发生变化时触发

构造函数 MutationObserver

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Firefox和Chrome早期版本中带有前缀
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver

// 选择目标节点
var target = document.querySelector('#some-id');
 
// 创建观察者对象
var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    console.log(mutation.type);
  });    
});
 
// 配置观察选项:
var config = { attributes: true, childList: true, characterData: true }
 
// 传入目标节点和观察选项
observer.observe(target, config);
 
// 随后,你还可以停止观察
observer.disconnect();

WebSocket 简述原理

WebSocket 协议基于 TCP,解决过去为了实现即时通讯而采用的轮询方案,解决了大量交换 HTTP header,信息交换效率低的问题。在浏览器和服务器之间建立双向连接。

冒泡 + 快排 + 插入排序原理等

详见:JavaScript 排序算法汇总

网络协议 HTTP HTTPS HTTP2 的基本概念等

自适应布局,移动端自适应等问题

设计模式

这方面被问到的比较多的:观察者模式,工厂模式,职责链模式等等

主要是经常涉及应用于 js 开发组件。比如如何去设计一个前端UI组件,应该公开出哪些方法,应该提供哪些接口,应该提供哪些事件。哪部分逻辑流程应该开放出去让用户自行编写,如何实现组件与组件之间的通信,如何实现高内聚低耦合,如何实现组件的高复用等等。

你怎么看 XXX

结合框架原理,社区环境,技术选型(技术、业务、人)等

本文版权归 yangzj1992 所有。来源青春样博客(qcyoung.com),商业转载请联系本人获得授权,非商业转载请注明出处。


本博客采用 Disqus 作为评论解决方案,目前 Disqus 经常被 GFW 封锁,若想参与评论请翻墙访问本站或将 disqus.com 添加至翻墙白名单。你也可以通过导航栏上的社交网站与我联系